﻿using System;
using System.IO;
using RazorEngine;
using RazorEngine.Templating;
using SqlSugar;
using Crossroad.Utils.Extensions;
using Crossroad.Utils.Helper;
using Crossroad.Core;
using CodeGenerator.Helper;

namespace CodeGenerator
{
    public class GeneratorContext : DataUtil
    {
        public static string AppPath { get; set; } = AppDomain.CurrentDomain.BaseDirectory;
        public static string OutputPath { set; get; }

        /// <summary>
        /// 是否需要生成controller代码
        /// </summary>
        public static bool MakeControllers { get; set; }

        public GeneratorContext(string rootPath)
        {
            AppPath = Path.GetFullPath("../../../../");
            OutputPath = rootPath ?? Path.GetFullPath("../../../../");

            Console.WriteLine("你确定要生成代码吗？y/n");
            var input = Console.ReadLine();
            if (input == null || !input.ToLower().Equals("y"))
                return;

            Console.WriteLine("是否需要生成Controller？y/n");
            input = Console.ReadLine();
            MakeControllers = input.NotNull() && input.ToLower().Equals("y");
            if(!MakeControllers)
                Console.WriteLine("不生成Controller。");

            Console.WriteLine("请输入表名(多表输入表前缀名 + *)：");
            input = Console.ReadLine();

            Create(input);
        }

        public void Create(string tableName)
        {
            if (tableName.IsNullOrEmpty())
                return;
            
            var tables = db.DbMaintenance.GetTableInfoList().FindAll(row =>
            {
                if (tableName.LastIndexOf('*') == tableName.Length - 1)
                    return row.Name.IndexOf(tableName.DelLastChar('*'), StringComparison.Ordinal) == 0;
                else
                    return row.Name.Equals(tableName);
            });
            var excludePrefix = "";
            if (tables.Count == 0)
                return;

            Console.WriteLine("请输入生成的Model类 表名中需要排除的前缀名：");
            excludePrefix = Console.ReadLine() ?? "";
            Console.WriteLine("请输入生成Model类输出模块的项目相对路径：");
            var outputNamespace = Console.ReadLine();
            if (outputNamespace.IsNullOrEmpty())
                return;

            //Console.WriteLine("选择Service类模板：1=Service.txt, 2=Service.Std.txt ？");
            //var tmpChoose = Console.ReadLine() ?? "";
            //tmpChoose = tmpChoose.Equals("2") ? "Service.Std.txt" : "Service.txt";
            var serviceChoose = "Service.Std.txt";
            var controllerChoose = "Controller.Std.txt";
            var dtoChoose = "Dto.Std.txt";
            var serviceTemplate = File.ReadAllText($@"{AppPath}\CodeGenerator\Template\{serviceChoose}");
            var interfaceTemplate = File.ReadAllText($@"{AppPath}\CodeGenerator\Template\I{serviceChoose}");
            var controllerTemplate = File.ReadAllText($@"{AppPath}\CodeGenerator\Template\{controllerChoose}");
            var dtoTemplate = File.ReadAllText($@"{AppPath}\CodeGenerator\Template\{dtoChoose}");

            //主键列
            DbColumn primaryKeyColumn = new DbColumn();
            
            //循环表
            tables.ForEach(table =>
            {
                var objectName = (excludePrefix.IsNullOrEmpty() ? table.Name : table.Name.Replace(excludePrefix , "")).ToCamelCase().FirstLetterUpper();
                db.MappingTables.Add(objectName, table.Name);
                //循环列
                db.DbMaintenance.GetColumnInfosByTableName(table.Name).ForEach(column =>
                {
                    //属性名称
                    var propertyName = column.DbColumnName.ToCamelCase();
                    //拿到主键列名
                    if (column.IsPrimarykey)
                    {
                        primaryKeyColumn.Name = propertyName;
                        primaryKeyColumn.DataType = column.DataType;
                    }

                    db.MappingColumns.Add(propertyName, column.DbColumnName, objectName);
                });

                var classNamespace = outputNamespace.Replace(@"\", ".");

                /**
                 * 生成model
                 */
                if (FileHelper.IsExistFile($@"{OutputPath}\{outputNamespace}\Model\{objectName}.cs") == false)
                {
                    db.DbFirst.Where(table.Name)
                        .IsCreateDefaultValue()
                        .IsCreateAttribute()
                        //Model类模板
                        .SettingClassTemplate(old =>
                        {
                            return old.Replace("{Namespace}", $"{classNamespace}.Model");
                        })
                        //命名空间
                        .SettingNamespaceTemplate(old => old)
                        //属性描述
                        .SettingPropertyDescriptionTemplate(old => old)
                        //属性模板
                        .SettingPropertyTemplate(old => old)
                        //构造函数
                        .SettingConstructorTemplate(old =>
                        {
                            return old;
                        })
                        .CreateClassFile($@"{OutputPath}\{outputNamespace}\Model");
                }

                /**
                 * 生成service
                 */
                //从文件中读出模板内容
                ServiceParameter model = new ServiceParameter()
                {
                    Description = table.Description,
                    PKName = primaryKeyColumn.Name,
                    PKDataType = primaryKeyColumn.DataType,
                    Name = objectName,
                    ClassNamespace = classNamespace,
                    ServiceNamespace = $"{classNamespace}.Service",
                    ModelNamespace = $"{classNamespace}.Model",
                    ControllerNamespace = $"{classNamespace}.Controller",
                    DtoNamespace = $"{classNamespace}.Dto",
                };
                /**
                 * 业务逻辑代码生成
                 */
                var result = Engine.Razor.RunCompile(serviceTemplate, "service", model.GetType(), model);
                var file = $@"{OutputPath}\{outputNamespace}\Service\Impl\{objectName}Service.cs";
                if (FileHelper.IsExistFile(file) == false)
                    FileHelper.CreateFile(file, result, System.Text.Encoding.UTF8);
                /**
                 * 接口代码生成
                 */
                result = Engine.Razor.RunCompile(interfaceTemplate, "interface", model.GetType(), model);
                file = $@"{OutputPath}\{outputNamespace}\Service\I{objectName}Service.cs";
                if (FileHelper.IsExistFile(file) == false)
                    FileHelper.CreateFile(file, result, System.Text.Encoding.UTF8);
                /**
                 * 接口控制器代码生成
                 */
                if (MakeControllers)
                {
                    result = Engine.Razor.RunCompile(controllerTemplate, "controller", model.GetType(), model);
                    file = $@"{OutputPath}\{outputNamespace}\Controller\{objectName}Controller.cs";
                    if (FileHelper.IsExistFile(file) == false)
                        FileHelper.CreateFile(file, result, System.Text.Encoding.UTF8);

                    result = Engine.Razor.RunCompile(dtoTemplate, "dto", model.GetType(), model);
                    file = $@"{OutputPath}\{outputNamespace}\Dto\{objectName}Dto.cs";
                    if (FileHelper.IsExistFile(file) == false)
                        FileHelper.CreateFile(file, result, System.Text.Encoding.UTF8);
                }

            });
        }


    }

}
